/**
 * scheme.c
 */

#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#include "Base.h"

#include "scheme.h"

WeekTime getWeekTime(void) {
	time_t tTime;
	time(&tTime);
	struct tm *pTime = gmtime(&tTime);
	WeekTime wt = {pTime->tm_wday, pTime->tm_hour, pTime->tm_min, pTime->tm_sec};
	return wt;
}

WeekTime secToWeekTime(int sec) {
	WeekTime wt = {0, 0, 0, 0};
	if (sec > 0) {
		wt.week = sec / (24 * 60 * 60);
		wt.hour = (sec % (24 * 60 * 60)) / (60 * 60);
		wt.minute = (sec % (60 * 60)) / 60;
		wt.second = sec % 60;
	}
	return wt;
}

/*
  *		|_____________|			time
  *			|______________|	first case
  *	|______________________|	second case
  */
int getWeekTimeContSec(WeekTime time, Scheme *pList) {
	int startSec = weekTimeToSec(time);
	int endSec = startSec;
	Scheme *pTemp = pList;
	while (pTemp != NULL) {
		int ss = weekTimeToSec(pTemp->startTime);
		int es = weekTimeToSec(pTemp->endTime);
		if (ss <= endSec && es > endSec) {
			endSec = es;
		}

		pTemp = pTemp->pNext;
	}

	return endSec - startSec;
}

bool isInSchemeListRange(Scheme *pList, WeekTime time) {
	bool inRange = false;	// when time in any sche node range, will be true
	int startSec;
	int endSec;
	int sec = weekTimeToSec(time);

	Scheme *pScheme = pList;
	while (pScheme != NULL) {
		startSec = weekTimeToSec(pScheme->startTime);
		endSec = weekTimeToSec(pScheme->endTime);
		if (startSec <= sec && sec < endSec) {
			inRange = true;
			break;
		}
		/*
		LOGINFO("scheme FROM %d %d %d %d -------- TO %d %d %d %d\n", pScheme->startTime.week,
				pScheme->startTime.hour, pScheme->startTime.minute, pScheme->startTime.second,
				pScheme->endTime.week, pScheme->endTime.hour, pScheme->endTime.minute, pScheme->endTime.second);
		*/
		pScheme = pScheme->pNext;
	}
	// LOGINFO("time %d %d %d %d is %s range\n", time.week, time.hour, time.minute, time.second, inRange ? "in" : "out");
	return inRange;
}

Scheme *allocSchemeList(char *pBuff) {
	int num = pBuff[0];
	if (num == 0) {
		return NULL;
	}
	
	char *pConfBuff = pBuff + 1;
	int weekTimeSize = sizeof(WeekTime);
	Scheme *pList = NULL;
	Scheme *pTail = NULL;
	int i;
	for (i = 0; i < num; i++) {
		if (pList == NULL) {	// head
			pList = calloc(1, sizeof(Scheme));
			pTail = pList;
		} else {
			pTail->pNext = calloc(1, sizeof(Scheme));
			pTail = pTail->pNext;
		}
		
		memcpy(&pTail->startTime, pConfBuff, weekTimeSize);	// WeekTime is ONE byte align
		memcpy(&pTail->endTime, pConfBuff + weekTimeSize, weekTimeSize);
		pConfBuff += weekTimeSize * 2;
	}
	
	return pList;
}

void freeSchemeFromList(Scheme *pScheme, Scheme **ppList) {
	Scheme *pCurr = *ppList;
	while (pCurr != NULL) {
		if (pCurr == *ppList && pCurr == pScheme) {	// head
			*ppList = pCurr->pNext;
			free(pCurr);
			break;
		}

		Scheme *pNext = pCurr->pNext;
		if (pNext != NULL && pNext == pScheme) {	// not in head
			pCurr->pNext = pNext->pNext;
			free(pNext);
			break;
		}

		pCurr = pNext;
	}
}

void freeSchemeList(Scheme *pList) {
	Scheme *pScheme = pList;
	Scheme *pNext = NULL;
	while (pScheme != NULL) {
		pNext = pScheme->pNext;
		free(pScheme);
		pScheme = pNext;
	}
}

Scheme *allocSchemeList_num_calloc(char *pBuff) {		// alloc num at once
	int num = pBuff[0];
	if (num == 0) {
		return NULL;
	}
	
	char *pConfBuff = pBuff + 1;
	int weekTimeSize = sizeof(WeekTime);
	Scheme *pList = (Scheme *) calloc(num, sizeof(Scheme));
	if (pList == NULL) {
		LOGERROR("pList == NULL\n");
		return NULL;
	}

	int i;
	Scheme *pScheme = pList;
	for (i = 0; i < num; i++) {
		memcpy(&pScheme->startTime, pConfBuff, weekTimeSize);	// WeekTime is ONE byte align
		memcpy(&pScheme->endTime, pConfBuff + weekTimeSize, weekTimeSize);
		if (i == num -1) {	// tail
			pScheme->pNext = NULL;
		} else {
			pScheme->pNext = pScheme + 1;	// pSchemeList is a continue buffer
		}
		
		pScheme = pScheme->pNext;
		pConfBuff += weekTimeSize * 2;
	}
	
	return pList;
}

int getSchemeListBuffSize(Scheme *pList) {
	Scheme *pScheme = pList;
	int num = 0;
	while (pScheme != NULL) {
		num++;
		pScheme = pScheme->pNext;
	}

	return sizeof(WeekTime) * num * 2 + 1;
}

int schemeListToBuff(char *pBuff, int buffSize, Scheme *pList) {
	int weekTimeSize = sizeof(WeekTime);
	int num = 0;
	int needSize = getSchemeListBuffSize(pList);
	if (needSize > buffSize) {
		LOGERROR("needSize > buffSize\n");
		return -1;
	}

	char *pConfBuff = pBuff + 1;
	Scheme *pScheme = pList;	// back to head
	while (pScheme != NULL) {
		memcpy(pConfBuff, &pScheme->startTime, weekTimeSize);
		memcpy(pConfBuff + weekTimeSize, &pScheme->endTime, weekTimeSize);
		num++;
		pConfBuff += weekTimeSize * 2;
		pScheme = pScheme->pNext;
	}
	pBuff[0] = num;

	return needSize;
}

